I18N Implementation in ZK

From Documentation
DocumentationSmall Talks2007MarchI18N Implementation in ZK
I18N Implementation in ZK

Author
Minjie Zha, Student, Software Institute specialising Software Engineering at Nanjing University, China.
Date
March 25, 2007
Version
Applicable to ZK 2.2.0 and later.


Purpose

Internationalization is becoming more and more important in today's software development. For a web site, multiple language support seems to be a necessary feature. In this article, I am going to introduce how to implement I18N for your web pages with org.zkoss.util.resource.Labels and taglib built in ZK. A general login demo is presented to show you how to use them.


A General Login Demo

Following is a ZUL file, which displays a general login form:

<?xml version="1.0" encoding="UTF-8"?>
<?page title="I18N Login Demo"?>
<div align="center">
    <window border="none" width="40%">   
        <separator spacing="50px"/>
        <label id="errLabel" style="color: red"/>
        <grid>
            <rows>
                <row>
                    <label value="username:"/>
                    <textbox id="namebox" constraint="no empty"/>
                </row>
                <row>
                    <label value="password:"/>
                    <textbox id="passwordbox" type="password" constraint="no empty"/>
                </row>
                <row spans="2" align="center">
                    <button label="login" onClick="onLogin()"/>
                </row>
            </rows>
        

        <zscript>
            void onLogin(){ 
               // add code here
            }
        </zscript>
    </window>
</div>

It is very simple, so I will not go to details.


Add I18N Support

However, the previous index.zul can't display different languages according to the client locale. Now, we are going make this by using labels.

A label is a Localedependent string that is stored in i3-label*.properties. We need two steps:

1. Write all localedependent strings into i3-label*.properties
2. Read them from i3-label*.properties with org.zkoss.util.resource.Labels


So, firstly, create a file named i3-label_lang_CNTY.properties in your webroot/WEB-INF directory.lang and CNTY should be replaced with the right language and country name. Such as i3-label_ en_US.properties, i3-label_zh_CN.properties and i3-label_ja.properties. When a Localedependent label is about to retrieved, the matched i3-label_ang_CNTY.properties will be loaded. And the i3-label.properties file will be loaded when there are no matched locale file.


Here, we create two files in webroot/WEB-INF directory, i3-label_en_US.properties for English in USA: i3-label_en_US.properties:

# en_US
app.username=username:
app.password=password:
app.login=login


and i3-label_zh_CN.properties for Chinese in China: i3-label_zh_CN.properties:

# zh_CN
app.username=用戶名
app.password= 密碼
app.login=登錄


Secondly, we shall read those strings with org.zkoss.util.resource.Labels. We need to modify index.zul into: index.zul

<?xml version="1.0" encoding="UTF-8"?>
<?page title="I18N Login Demo"?>
<div align="center">
    <window border="none" width="40%">
        <separator spacing="50px"/>
        <label id="errLabel" style="color: red"/>
        <grid>
            <rows>
                <zscript>
                    String username = org.zkoss.util.resource.Labels.getLabel("app.username");
                    String password = org.zkoss.util.resource.Labels.getLabel("app.password");
                    String login = org.zkoss.util.resource.Labels.getLabel("app.login");
                </zscript>
                <row>
                    <label value=""/>
                    <textbox id="namebox" constraint="no empty"/>
                </row>
                <row>
                    <label value=""/>
                    <textbox id="passwordbox" type="password" constraint="no empty"/>
                </row>
                <row spans="2" align="center">
                    <button label="" onClick="onLogin()"/>
                </row>
            </rows>
        </grid>

        <zscript>
            void onLogin(){ 
               // add code here
            }
        </zscript>
    </window>
</div>

So, when visiting index.zul with Firefox, you will get:

En US.png


Change your Firefox's language to zh_CN, and reload the page. Now, you will get:

Zh CN.png


Using Taglib

Sometimes, you may want to use labels in EL expression. This requires two steps:

1. Include TLD file in your ZUL page: <?taglib uri="http://www.zkoss.org/dsp/web/core"prefix="c"?>
2. Use to retrieve labels


Now, the index.zul changed to index.zul

<?xml version="1.0" encoding="UTF-8"?>
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<?page title="I18N Login Demo"?>
<div align="center">
    <window border="none" width="40%">
        <separator spacing="50px"/>
        <label id="errLabel" style="color: red"/>
        <grid>
            <rows>
                <row>
                    <label value=""/>
                    <textbox id="namebox" constraint="no empty"/>
                </row>
                <row>
                    <label value=""/>
                    <textbox id="passwordbox" type="password" constraint="no empty"/>
                </row>
                <row spans="2" align="center">
                    <button label="" onClick="onLogin()"/>
                </row>
            </rows>
        </grid>

        <zscript>
            void onLogin(){ 
               // add code here
            }
        </zscript>
    </window>
</div>

Add Parameters to Label

Till now, the onLogin() method is still empty. So we are going to add code in it. As an example, we will make login failed all the time, and set error message to errLabel. The error message may be something like “Your username _username does not exist or password _password is not correct”. _username and _password are depend on the user input. If we can add parameter to label string, that will be very good. So I write a class edu.nju.i18n.Labels, which has method public static String getLabel(String key, String[] parameters) . Please read more about it in the source code for this article.

Now, onLogin() method looks like:

<zscript>
            import edu.nju.i18n.Labels;
            
            void onLogin(){ 
               String username = namebox.getValue();
               String password = passwordbox.getValue();
               errLabel.setValue(Labels.getLabel("app.errMsg",new String[]{username,password}));
            }
</zscript>


After click login button, you will get:

Failed.png

You can also change your Firefox's language and see what you get.


Sample

Source Code: I18N.zip


Reference

1. ZK Developer's Reference/Internationalization


Ruler.gif


Minjie Zha is a bachelor's student in Software Institute specialising Software Engineering at Nanjing University, China. He did several projects with J2ME and J2EE. He is interested in new technologies and open source projects such as Tapestry, Spring, Lucene, Ruby, and also ZK.




Copyright © Minjie Zha. This article is licensed under GNU Free Documentation License.